using System;
using System.Threading;

namespace UnityEngine.Recorder
{
	public class RecordingSession : IDisposable
	{
		public Recorder m_Recorder;

		public GameObject m_RecorderGO;

		public double m_CurrentFrameStartTS;

		public double m_RecordingStartTS;

		private int m_FrameIndex;

		private int m_InitialFrame;

		private int m_FirstRecordedFrameCount = -1;

		private float m_FPSTimeStart;

		private float m_FPSNextTimeStart;

		private int m_FPSNextFrameCount;

		public DateTime m_SessionStartTS;

		public RecorderSettings settings => m_Recorder.settings;

		public bool recording => m_Recorder.recording;

		public int frameIndex => m_FrameIndex;

		public int RecordedFrameSpan => (m_FirstRecordedFrameCount != -1) ? (Time.renderedFrameCount - m_FirstRecordedFrameCount) : 0;

		public float recorderTime => (float)(m_CurrentFrameStartTS - (double)settings.m_StartTime);

		private void AllowInBackgroundMode()
		{
			if (!Application.runInBackground)
			{
				Application.runInBackground = true;
				if (Verbose.enabled)
				{
					UnityEngine.Debug.Log("Recording sessions is enabling Application.runInBackground!");
				}
			}
		}

		public bool SessionCreated()
		{
			try
			{
				AllowInBackgroundMode();
				m_RecordingStartTS = Time.time / Time.timeScale;
				m_SessionStartTS = DateTime.Now;
				m_Recorder.SessionCreated(this);
				return true;
			}
			catch (Exception exception)
			{
				UnityEngine.Debug.LogException(exception);
				return false;
			}
		}

		public bool BeginRecording()
		{
			try
			{
				if (!settings.isPlatformSupported)
				{
					UnityEngine.Debug.LogError($"Recorder {m_Recorder.GetType().Name} does not support current platform");
					return false;
				}
				AllowInBackgroundMode();
				m_RecordingStartTS = Time.time / Time.timeScale;
				m_Recorder.SignalInputsOfStage(ERecordingSessionStage.BeginRecording, this);
				if (!m_Recorder.BeginRecording(this))
				{
					return false;
				}
				m_InitialFrame = Time.renderedFrameCount;
				m_FPSTimeStart = Time.unscaledTime;
				return true;
			}
			catch (Exception exception)
			{
				UnityEngine.Debug.LogException(exception);
				return false;
			}
		}

		public virtual void EndRecording()
		{
			try
			{
				m_Recorder.SignalInputsOfStage(ERecordingSessionStage.EndRecording, this);
				m_Recorder.EndRecording(this);
			}
			catch (Exception exception)
			{
				UnityEngine.Debug.LogException(exception);
			}
		}

		public void RecordFrame()
		{
			try
			{
				m_Recorder.SignalInputsOfStage(ERecordingSessionStage.NewFrameReady, this);
				if (!m_Recorder.SkipFrame(this))
				{
					m_Recorder.RecordFrame(this);
					m_Recorder.recordedFramesCount++;
					if (m_Recorder.recordedFramesCount == 1)
					{
						m_FirstRecordedFrameCount = Time.renderedFrameCount;
					}
				}
				m_Recorder.SignalInputsOfStage(ERecordingSessionStage.FrameDone, this);
			}
			catch (Exception exception)
			{
				UnityEngine.Debug.LogException(exception);
			}
			if (m_Recorder.settings.m_FrameRateMode == FrameRateMode.Variable || (m_Recorder.settings.m_FrameRateMode == FrameRateMode.Constant && m_Recorder.settings.m_SynchFrameRate))
			{
				int num = Time.renderedFrameCount - m_InitialFrame;
				double num2 = 1.0 / m_Recorder.settings.m_FrameRate;
				float num3 = Time.unscaledTime - m_FPSTimeStart;
				double num4 = num2 * (double)(num + 1);
				int num5 = (int)((num4 - (double)num3) * 1000.0);
				if (num5 > 2)
				{
					if (Verbose.enabled)
					{
						UnityEngine.Debug.Log($"Recording session info => dT: {num3:F1}s, Target dT: {num4:F1}s, Retarding: {num5}ms, fps: {(float)num / num3:F1}");
					}
					Thread.Sleep(Math.Min(num5, 1000));
				}
				else if ((double)num5 < 0.0 - num2)
				{
					m_InitialFrame--;
				}
				else if (Verbose.enabled)
				{
					UnityEngine.Debug.Log($"Recording session info => fps: {(float)num / num3:F1}");
				}
				if (num % 50 == 49)
				{
					m_FPSNextTimeStart = Time.unscaledTime;
					m_FPSNextFrameCount = Time.renderedFrameCount;
				}
				if (num % 100 == 99)
				{
					m_FPSTimeStart = m_FPSNextTimeStart;
					m_InitialFrame = m_FPSNextFrameCount;
				}
			}
			m_FrameIndex++;
		}

		public void PrepareNewFrame()
		{
			try
			{
				AllowInBackgroundMode();
				m_CurrentFrameStartTS = (double)(Time.time / Time.timeScale) - m_RecordingStartTS;
				m_Recorder.SignalInputsOfStage(ERecordingSessionStage.NewFrameStarting, this);
				m_Recorder.PrepareNewFrame(this);
			}
			catch (Exception exception)
			{
				UnityEngine.Debug.LogException(exception);
			}
		}

		public void Dispose()
		{
			if (m_Recorder != null)
			{
				try
				{
					if (recording)
					{
						EndRecording();
					}
				}
				catch (Exception exception)
				{
					UnityEngine.Debug.LogException(exception);
				}
				UnityHelpers.Destroy(m_Recorder);
				UnityHelpers.Destroy(m_RecorderGO);
			}
		}
	}
}
